Post not yet marked as solved
Starting on Xcode 15.3 and 15.4 my SwiftUI Previews stopped working with the following error:
== PREVIEW UPDATE ERROR:
LinkDylibError: Failed to build ContentView.swift
Linking failed: linker command failed with exit code 1 (use -v to see invocation)
ld: warning: search path '/Applications/Xcode.app/Contents/SharedFrameworks-iphonesimulator' not found
Undefined symbols for architecture arm64:
"static MyLibrary.DisplayUtil.getText() -> Swift.String", referenced from:
closure #1 () -> SwiftUI.Text in (extension in Demo_Broken_Preview_PreviewReplacement_ContentView_1):Demo_Broken_Preview.ContentView.(__preview__body in _1BA320C8FB5388C953E1E463345C3D72).getter : some in ContentView.1.preview-thunk.o
"type metadata accessor for MyLibrary.DisplayUtil", referenced from:
closure #1 () -> SwiftUI.Text in (extension in Demo_Broken_Preview_PreviewReplacement_ContentView_1):Demo_Broken_Preview.ContentView.(__preview__body in _1BA320C8FB5388C953E1E463345C3D72).getter : some in ContentView.1.preview-thunk.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
After much trial and error, I narrowed it down to my SwiftUI views using properties or functions inside components in Swift Packages.
This is a simple example of my Swift Package:
public class DisplayUtil {
public func getText() -> String {
return "Text"
}
public static func getText() -> String {
return "Text"
}
}
And my SwiftUI View
import SwiftUI
import MyLibrary
struct ContentView: View {
var body: some View {
VStack {
Text(DisplayUtil.getText())
}
.padding()
}
}
#Preview {
ContentView()
}
The same code works fine on Xcode 15.2
Link to the sample project:
https://www.icloud.com/iclouddrive/0c00AD0esi2PwqqiRggokfwGw#Demo%5FBroken%5FPreview
Is anybody else having a similar issue?
Post not yet marked as solved
I have a complex project that includes a background process sending requests to the backend for updates. It sends requests once per second.
So, I have the MyView where the PresetPicker is located. When I open the PresetPicker and try to scroll down, it keeps pushing me back up every second. PresetPicker redraws itself every second due to some changes from the background process. (Turning off the background process confirmed that everything works fine.)
I wrapped my PresetPicker in EquatableView, added a bunch of logs triggered by changes/redraws of the PresetPicker, but the logs are empty and EquatableView didn't help.
I tried setting breakpoints; they trigger when the PresetPicker first appears but don't trigger afterward. How can I fix/debug this?
Here is some code:
struct PresetPicker: View, Equatable {
var body: some View {
Menu {
Text("1")
Text("2")
Text("3")
Text("4")
} label: {
Text("menu")
}
}
}
struct MyView: View {
var body: some View {
EquatableView(content:
PresetPicker()
)
}
}
Post not yet marked as solved
Document based app on 17.5 has two back buttons, but 17.0 as only one. Did anyone experience this?
Post not yet marked as solved
Hi, community:
I was trying to move from application(_:open:options:) (UIKit) to
onOpenURL(perform:) (SwiftUI). Maybe there's something that I'm missing.
In UIKit you can say to the system that you won't handle the URL then the app is not opened, but when I use onOpenURL(perform:) it is always opened. Is there any way to achieve the same behavior?
Thanks in advance.
Post not yet marked as solved
I've run into a problem related to navigation links in child Views containing a SwiftData @Query and a predicate.
When tapping on a NavigationLinks, the containing View is invalidated pausing the UI. When tapping back, the View is invalidated a second time during which time the View ignores any new taps for navigation leading to a poor user experience.
A complete example:
import SwiftUI
import SwiftData
@Model
final class Item {
var num: Int
init(num: Int) {
self.num = num
}
}
@main
struct TestSwiftDataApp: App {
var sharedModelContainer: ModelContainer = {
let schema = Schema([Item.self])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
let container: ModelContainer
do {
container = try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
// Add some sample data
Task { @MainActor in
for i in 0...1000 {
container.mainContext.insert(Item(num: i))
}
}
return container
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(sharedModelContainer)
}
}
extension Color {
static func random() -> Color {
Color(red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1))
}
}
struct ContentView: View {
var body: some View {
NavigationStack {
SubView()
.navigationDestination(for: Item.self) { item in
Text("Item at \(item.num)")
}
}
}
}
struct SubView: View {
@Environment(\.modelContext) private var modelContext
@Query(filter: #Predicate<Item> { item in
item.num < 20
}, sort: \.num) private var items: [Item]
var body: some View {
let _ = Self._printChanges()
List {
ForEach(items) { item in
NavigationLink(value: item) {
Text("Item \(item.num)")
}.background(Color.random())
}
}
}
}
The background colors of cells will shift every invalidation. In addition there's some debugging in there to show what's happening. When running it, I get
SubView: @self, @identity, _modelContext, @128, @144 changed.
SubView: @self changed.
SubView: @dependencies changed.
Then I tap on an item and it invalidates:
SubView: @self changed.
Tapping back invalidates it again during which time the UI ignores new taps:
SubView: @self changed.
The odd thing is, this behavior doesn't happen if the NavigationStack is moved to the child View with the NavigationLinks like this:
struct ContentView2: View {
var body: some View {
SubView2()
}
}
struct SubView2: View {
@Environment(\.modelContext) private var modelContext
@Query(filter: #Predicate<Item> { item in
item.num < 20
}, sort: \.num) private var items: [Item]
var body: some View {
let _ = Self._printChanges()
NavigationStack {
List {
ForEach(items) { item in
NavigationLink(value: item) {
Text("Item \(item.num)")
}.background(Color.random())
}
}
.navigationDestination(for: Item.self) { item in
Text("Item at \(item.num)")
}
}
}
}
When running this, there's one less change as well and no invalidations on tap or back:
SubView: @self, @identity, _modelContext, @128, @144 changed.
SubView: @dependencies changed.
The problem also doesn't happen if the @Query does not have a filter #Predicate.
Unfortunately, the application in question has a deeper hierarchy where views with a @Query with a predicate can navigation to other views with a @Query and predicate, so neither solution seems ideal.
Is there some other way to stop the invalidations from happening?
Post not yet marked as solved
When I run the code below, the trace, "Called", is shown 3-4 times initially. If I click on a color row, the trace shows 9 times. Why is that?
If I comment out the line, @Environment(\.dismiss) private var dismiss, the trace shows only 1 time, as expected.
I've read a number of reports regarding dismiss() which seems to be very brittle. It often causes an infinite loop. But I need to dismiss a view. Its older counterpart, @Environment(\.presentationMode), seems to cause infinite loop at times. Are there other ways to dismiss a view without suffering these issues?
struct TestNavigationLink: View {
@Environment(\.dismiss) private var dismiss
var body: some View {
let _ = print("Called")
NavigationStack {
List {
NavigationLink("Mint") { ColorDetail(color: .mint) }
}
.navigationTitle("Colors")
}
} // body
struct ColorDetail: View {
var color: Color
var body: some View {
color.navigationTitle(color.description)
}
}
}
Post not yet marked as solved
I get this error while migrating from ObservableObject to @Observable.
Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context
My original code:
struct SomeView: View {
@StateObject private var viewModel = ViewModel()
}
After migration:
@MainActor @Observable class BaseViewModel {
}
@MainActor class ViewModel: BaseViewModel {
}
struct SomeView: View {
@State private var viewModel = ViewModel()
}
As discussed here. It seems like @StateObject is adding @MainActor compliance to my View under the hood because it's wrappedValue and projectedValue properties are marked as @MainActor, while on @State they are not.
@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
@frozen @propertyWrapper public struct StateObject<ObjectType> : DynamicProperty where ObjectType : ObservableObject {
...
@MainActor public var wrappedValue: ObjectType { get }
....
@MainActor public var projectedValue: ObservedObject<ObjectType>.Wrapper { get }
}
One solution for this is to mark my View explicitly as @MainActor struct ViewModel: View but it have it side effects, for example code like:
Button(action: resendButtonAction) {
Text(resendButtonAttributedTitle())
}
Will result a warning
Converting function value of type '@MainActor () -> ()' to '() -> Void' loses global actor 'MainActor'
While could be easily solved by using instead
Button(action: { resendButtonAction() } ) {
Text(resendButtonAttributedTitle())
}
I still feel like marking the whole View explicitly as @MainActor is not a good practice.
Adding fake @StateObject property to my view also do the trick, but it's a hack (the same for @FetchRequest).
Can anyone think of a more robust solution for this?
Post not yet marked as solved
Sonoma 14.4.1 (did not test on 14.4)
Xcode 15.3
New Project
macOS
Document App
Run
View menu has "Enter Full Screen"
Do Command-N
View menu does not have "Enter Full Screen"
May need to open and close a few windows.
import SwiftUI
@main
struct testApp: App {
var body: some Scene {
DocumentGroup(newDocument: testDocument()) { file in
ContentView(document: file.$document)
}
.commands {
CommandGroup(replacing: CommandGroupPlacement.saveItem) {
}
}
}
}
File menu
Open Recent becomes NSMenuItem
Post not yet marked as solved
TabView {
SummaryView()
.toolbar(.hidden, for: .tabBar, .bottomBar)
.tabItem { Text("Title.Summary") }
.tag(TabItems.summary)
CalendarView()
.toolbar(.hidden, for: .tabBar, .bottomBar)
.tabItem { Text("Title.Calendar") }
.tag(TabItems.calendar)
EventTypeView()
.toolbar(.hidden, for: .tabBar, .bottomBar)
.tabItem { Text("Title.EventType") }
.tag(TabItems.group)
LectureView()
.toolbar(.hidden, for: .tabBar, .bottomBar)
.tabItem { Text("Title.Lecture") }
.tag(TabItems.lecture)
NotificationView()
.toolbar(.hidden, for: .tabBar, .bottomBar)
.tabItem { Text("Title.Notifications") }
.tag(TabItems.notification)
}
Tabbar is hidden when first opened but tabbar is appeared when I change tab selection.
I tested it on iOS 17.1, iOS 17.4, and this bug is only appeared in iOS 17.4.
Post not yet marked as solved
Fairly new to SwiftUI and using it for a school project. I keep getting this error and I have no idea how to fix it.
// AddToCartButton.swift
// ProducePal
//
import SwiftUI
struct AddToCartButton: View {
@EnvironmentObject var multicart: MultiCartManager
var product: Product
var body: some View {
VStack {
Button {
multicart.addToCart2(product: product)
} label: {
Text("Add to Cart")
.font(.headline)
.fontWeight(.semibold)
.foregroundColor(.white)
.padding()
.padding(.horizontal, 20)
.background(Color.blue)
.cornerRadius(10)
.shadow(radius: 20)
}
}
.buttonStyle(PlainButtonStyle())
}
}
struct AddToCartButton_Previews: PreviewProvider {
static var previews: some View {
AddToCartButton(product: productList[0])
.environmentObject(MultiCartManager())
}
}
Post not yet marked as solved
Using SwiftUI how can I get the click of a "Button" to change the wording of a "Label" and/or "Text" Field?
I have tried:-
let myLabel = Label {
Text("Text to be Changed"
.foregrorundStyle ......
} icon: {
......
}
....
.....
Button("Change Label Wording"){
myLabel.stringValue = "Changed text"
}
This gives me two problems (at least):
I cannot get the label to display
The myLabel.stringValue = "Changed text gives me the error:
Type '()' cannot conform to 'View'
Value of type 'Label<some View, some View>' has no member 'stringValue'
What have I done wrong?
Post not yet marked as solved
I have encountered a strange behavior these past couple weeks while dealing with Bluetooth, mostly because my code hasn't changed in over 6 months (maybe it was not working before and now it's correct, who knows). Essentially, when i pair with a bluetooth device for the first time, the onchange has stopped firing. I can post more exact code of the view but I didn't think it was necessary but after you select the device you want to connect to (for the first time) you get asked by the OS to pair. After successful connection, we read information from the device (the Profiles). Once I get that information, i set dataGathered to true which triggers .onChange and I can navigate. However, with this initial connection/pairing the .onChange is never triggered, but i know i'm getting my dataGathered set to true because my print is being set. Subsequent connections do cause .onChange to be triggered with 0 profiles and with many profiles. This code hasn't changed in months so i'm not sure if there's SwiftUI bug that's sprung up or what, or if there's an inherint issue with what i was doing and it's only now being caught.
struct DeviceSearchView: View {
@StateObject var connectedManager: Manager = Manager()
@StateObject var bluetoothListener: Listener = BluetoothListener()
var body: some View {
body
.onChange(self.bluetoothListener.connectedDevice) { device in
device.getData()
}
.onChange(self.connectedManager.dataGathered) { dataGathered in
// determine navigation
}
}
}
Manager Object
final class Manager: ObservedObject, BTDelegate, Identifiable /*i've tried adding/switching with Equatable but no change*/ {
@Published var dataGathered: Bool = false
@Published var profileList: Profile = [Profile]()
@Published var index: Int = 0
func updatedProfile(list: NSArray, selectedIndex: Int) {
print("profiles are in fact here")
var newList = [Profile]()
for element in list {
if let profile = element as? B50Profile {
print("\(profile.name)")
if !newList.contains(profile){
newList.append(profile)
}
}
}
self.profileList = newList
self.index = selectedIndex
self.dataGathered = true
print("data gathered is \(self.dataGathered)"
}
}
Post not yet marked as solved
Hello everyone
My goal is to create Apple's activity ring sparkle effect. So I found Paul Hudson's Vortex library. There is already a sparkle effect, but I don't know how to modify it to achieve my goal. Because I'm pretty new to SwiftUI animations. Does anyone have any idea how I could do this?
Vortex project: https://github.com/twostraws/Vortex
Post not yet marked as solved
Hi,
My app launches with a mixed immersive space. the Preferred Default Scene Session Role is set to Immersive Space Application Session Role.
ImmersiveSpace(id: "sceneSpace"){
ImmersiveView()
.environmentObject(modelObject)
}.immersionStyle(selection: .constant(.mixed), in: .mixed)
Other WindowGroups are opened too.
Problem:
When the x button (bottom left corner) is tapped on any WindowGroup the immersive space is dismissed.
When the user opens the app again the immersive space is gone.
The same happens when the user opens the Home Screen.
How can I keep the same immersive space when the app is opened again.
Thank you!
Post not yet marked as solved
I'm developing an app with a chart in SwiftUI. I want the following block of code to run when the chart is clicked. On my personal iPhone, the app works flawlessly. But when I try it in the simulator it crashes and gives me about 5-10 of the following errors. When I remove the @Query macro from the code block, the application does not crash in the simulator, but I continue to get the errors I mentioned. If I do not run the following code block, I do not get the errors I mentioned.
struct SaleDetailView: View {
@Query(filter: #Predicate<Registration> {
!$0.activeRegistration
}) private var regs: [Registration]
var body: some View {
VStack {
DailySaleView()
}
.padding()
}
}
Thank you in advance for your answers. Do not hesitate to ask if you have any questions.
Thanks, MFS
Post not yet marked as solved
Hi, guys.
I am preparing to develop a Vision Pro app with Unity.
The Play to Device, which connects Unity Engine and Vision Pro, worked well, and there was no problem with the connection with Vision Pro simulator.
But when I tried to connect Xcode and Vision Pro, I couldn't see Vision Pro itself in the device list. (The iPhone 11, which was wired as a test, recognizes well.)
I looked up the forum and it was simple to connect. The link to the post I found is below.
https://forums.developer.apple.com/forums/thread/746464
I don't know why it's not working even though I look up YouTube.
Leaving my work environment, I'd appreciate it if you could leave a helpful answer.
MacBook : M2 MacBook
Xcode Ver. : 15.3
VisionPro Ver. : 1.1.2
Developer accounts: All use the same Apple developer account
Post not yet marked as solved
I am making an app in SwiftUI, but the backend code relies on python and cannot be converted to swift. How can I get the file to run?
Post not yet marked as solved
Hello, fairly new to Swift, I come from a React Native background. One of the hardest things I'm finding is simply customising the screen headers in the navigation. I've managed to do it using a custom modifier that uses .toolbar and ToolbarItem as shown below:
struct NavBar: ViewModifier {
let title: String
let showBackButton: Bool?
@Environment(\.dismiss) private var dismiss
func body(content: Content) -> some View {
return content
.toolbar {
if showBackButton == true {
ToolbarItemGroup(placement: .navigationBarLeading) {
Button(action: {
dismiss()
}) {
Image("BackButton")
}.padding(.top, 18)
}
}
ToolbarItem(placement: .principal) {
Text(title)
.font(Font.custom("Knight Vision", size: 28))
.foregroundColor(.white).padding(.top, 20)
}
}
.navigationBarBackButtonHidden(true)
}
}
This is all fine and suits my needs however I'm finding that the toolbar does not slide in with the rest of the screen when navigating to as screen with it on. I would expect the title to slide in with the other items on the screen. Especially since the toolbar does animate out, it just does not animate in.
Heres a video so you can see what I mean. Am I doing something wrong here? Is there a better way to do this?
[linkText](https://www.youtube.com/shorts/6M-glapBZz0
/)
Post not yet marked as solved
UPDATED: I determined the line causing the hang was .animation(.default, value: layout).
I'm seeing a strange issue when switching between a ScrollView/LazyVGrid and a List with my SwiftData but when toggling the layout it ends up freezing and I can't confirm what's causing the app to hang since there's no crash. I'm not getting much info from the debugger. Any help would be appreciated.
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@Query private var items: [Item]
let gridItemLayout = [ GridItem(.adaptive(minimum: 150))]
@State private var layout = Layout.grid
var body: some View {
NavigationStack {
ZStack {
if layout == .grid {
ScrollView {
LazyVGrid(columns: gridItemLayout, spacing: 5) {
ForEach(items) { item in
}
}
}
} else {
List {
ForEach(items) { item in
}
}
}
}
// MARK: HERE'S THE ERROR
.animation(.default, value: layout)
.navigationTitle("ScrollView")
.toolbar {
ToolbarItemGroup {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
Menu {
Picker("Layout", selection: $layout) {
ForEach(Layout.allCases) { option in
Label(option.title, systemImage: option.imageName)
.tag(option)
}
}
.pickerStyle(.inline)
} label: {
Label("Layout Options", systemImage: layout.imageName)
.labelStyle(.iconOnly)
}
}
}
}
}
}
@Model
public class Item: Codable {
public let id: String
public enum CodingKeys: String, CodingKey {
case id
}
public init(id: String) {
self.id = id
}
required public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(String.self, forKey: .id)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
}
}
Post not yet marked as solved
I tried animating the scrollTo() like so, as described in the docs. - https://developer.apple.com/documentation/swiftui/scrollviewreader
swift
withAnimation {
scrollProxy.scrollTo(index, anchor: .center)
}
the result is the same as if I do
swift
withAnimation(Animation.easeIn(duration: 20)) {
scrollProxy.scrollTo(progress.currentIndex, anchor: .center)
}
I tried this using the example from the ScrollViewReader docs.
With the result that up and down scrolling has exactly the same animation.
struct ScrollingView: View {
@Namespace var topID
@Namespace var bottomID
var body: some View {
ScrollViewReader { proxy in
ScrollView {
Button("Scroll to Bottom") {
withAnimation {
proxy.scrollTo(bottomID)
}
}
.id(topID)
VStack(spacing: 0) {
ForEach(0..100) { i in
color(fraction: Double(i) / 100)
.frame(height: 32)
}
}
Button("Top") {
withAnimation(Animation.linear(duration: 20)) {
proxy.scrollTo(topID)
}
}
.id(bottomID)
}
}
}
func color(fraction: Double) - Color {
Color(red: fraction, green: 1 - fraction, blue: 0.5)
}
}
struct ScrollingView_Previews: PreviewProvider {
static var previews: some View {
ScrollingView()
}
}